package top.fangwenmagician.calculationstring.operator;

import top.fangwenmagician.calculationstring.ProcessControl;
import top.fangwenmagician.calculationstring.exception.CalculationException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 括号运算符
 */
public class Brackets implements I_Operator {
    private final Pattern pattern = Pattern.compile("[（(][^）)]*[）)]");

    @Override
    public int priority() {
        return 127;
    }

    @Override
    public boolean isExist(String expression) throws Exception {
        return pattern.matcher(expression).find();
    }

    @Override
    public int peerPriority(String expression) throws Exception {
        Matcher matcher = pattern.matcher(expression);
        if (matcher.find()) {
            return expression.length() - matcher.start();
        } else {
            return -1;
        }
    }

    @Override
    public String calculation(String expression, ProcessControl processControl) throws Exception {
        Capture capture = getCapture(expression);
        String captureString = capture.getCaptureString();
        processControl.setLogProcessing(logText -> capture.getBeforeCaptureString() + logText + capture.getAfterCaptureString());
        String replaceString = processControl.calculation(captureString, processControl);
        expression = capture.replace(replaceString);
        processControl.setLogProcessing(null);
        processControl.removeLast();
        processControl.writeLog(expression);
        return expression;
    }

    /**
     * 获取捕获对象${@link Brackets.Capture}
     *
     * @param expression 表达式
     * @return 获对象${@link Brackets.Capture}
     * @throws Exception 捕获失败
     */
    private Capture getCapture(String expression) throws Exception {
        int weight = 0;
        Capture capture = new Capture(expression);
        char[] expressionCharArray = expression.toCharArray();
        for (int i = 0; i < expressionCharArray.length; i++) {
            char c = expressionCharArray[i];
            if (c == '(' || c == '（') {
                weight++;
                if (weight == 1) {
                    int beginIndex = i + 1;
                    if (beginIndex < expressionCharArray.length) {
                        capture.setBeginIndex(beginIndex);
                    } else {
                        throw new CalculationException(expression + " 捕获失败");
                    }
                }
            } else if (c == ')' || c == '）') {
                weight--;
                if (weight == 0) {
                    capture.setEndIndex(i);
                    return capture;
                } else if (weight < 0) {
                    throw new CalculationException(expression + " 括号捕获失败：反括号未闭合");
                }
            }
        }
        throw new CalculationException(expression + " 括号捕获失败：正括号未闭合");
    }

    /**
     * 捕获对象
     */
    protected class Capture {
        /**
         * 原始表达式
         */
        private final String expression;
        /**
         * 捕获的起始位置（包含）
         */
        private int beginIndex;
        /**
         * 捕获的结束位置（不包含）
         */
        private int endIndex;

        public Capture(String expression) {
            this.expression = expression;
        }

        /**
         * 获取被捕获的字符串
         *
         * @return 被捕获的字符串
         * @throws Exception 捕获失败：括号内字符串未空
         */
        public String getCaptureString() throws Exception {
            String captureString = expression.substring(beginIndex, endIndex);
            if ("".equals(captureString)) {
                throw new CalculationException(expression + " 捕获失败：括号内字符串为空");
            } else {
                return captureString;
            }
        }

        /**
         * 获取被捕获字符串前的字符串
         *
         * @return 被捕获字符串前的字符串
         */
        public String getBeforeCaptureString() throws Exception {
            return expression.substring(0, beginIndex);
        }

        /**
         * 获取被捕获字符串后的字符串
         *
         * @return 被捕获字符串后的字符串
         */
        public String getAfterCaptureString() throws Exception {
            return expression.substring(endIndex);
        }

        /**
         * 连同括号一起替换掉
         *
         * @param replaceString 要替换上去的字符串
         * @return 替换后的结果
         */
        public String replace(String replaceString) throws Exception {
            return expression.substring(0, beginIndex - 1) + replaceString + expression.substring(endIndex + 1);
        }

        public String getExpression() {
            return expression;
        }

        public int getBeginIndex() {
            return beginIndex;
        }

        public void setBeginIndex(int beginIndex) {
            this.beginIndex = beginIndex;
        }

        public int getEndIndex() {
            return endIndex;
        }

        public void setEndIndex(int endIndex) {
            this.endIndex = endIndex;
        }
    }
}


